﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using nanoCMS.Core;
using nanoCMS.Core.Extensions;
using nanoCMS.Store.Concrete;

namespace nanoCMS.Store.Providers {
	public class StoreOfferProvider {

#region Vars and Constructs
		private readonly WorldContext worldContext;
		private StoreEntities entities;
		private StoreCatalogItemProvider storeCatalogItemProvider;

		private StoreEntities Entities {
			get { return entities ?? (entities = new StoreEntities(worldContext.EntityConnectionString)); }
		}

		public StoreOfferProvider(WorldContext worldContext) {
			this.worldContext = worldContext;
			storeCatalogItemProvider = new StoreCatalogItemProvider(worldContext);
		}

#endregion

#region Offer

		/// <summary>
		/// 
		/// </summary>
		/// <param name="createdBy"></param>
		/// <param name="forUser"></param>
		/// <param name="storeId"></param>
		/// <param name="tax"></param>
		/// <param name="comment"></param>
		/// <param name="paymentType"></param>
		/// <param name="processedBy"></param>
		/// <param name="expireDate"></param>
		/// <param name="payedDate">Set only when is payed</param>
		/// <param name="adminComment"> can be null</param>
		/// <returns></returns>
		public StoreOffer CreateOffer(int createdBy, int forUser, int storeId, double? tax = null, 
			string comment = null, int? paymentType = null, int? processedBy = null, 
			DateTime? expireDate = null, DateTime? payedDate = null, string adminComment = null) {
			StoreOffer offer = new StoreOffer{
				CreatedBy = createdBy,
				ForUser = forUser,
				CreatedDate = DateTime.Now,
				ExpireDate = expireDate.IfNullSet(DateTime.Now.AddMonths(1)),
				PayedDate = payedDate,
				PaymentType = paymentType,
				ProcessedBy = processedBy,
				Tax = tax.IfNullSet(0),
				Sum = 0,
				Comment = comment.IfNullSet(String.Empty),
				AdminComment = adminComment.IfNullSet(String.Empty),
				StoreID = storeId,
				IsPayed = false,
				IsSealed = false
			};
			Entities.StoreOffers.AddObject(offer);
			Entities.SaveChanges();
			return offer;
		}

		public bool EditOffer(int storeOfferId, int createdBy, int forUser, DateTime createdDate, DateTime? expireDate,
			 DateTime? payedDate, int? paymentType, int? processedBy, double tax, decimal? sum,
			 string comment, string adminComment, int storeId, bool? isPayed, bool isSealed) {
			StoreOffer offer = Entities.StoreOffers.Where(o => o.OfferID == storeOfferId).SingleOrDefault();
			if (offer != null) {
				offer.CreatedBy = createdBy;
				offer.ForUser = forUser;
				offer.CreatedDate = createdDate;
				offer.ExpireDate = expireDate;
				offer.PayedDate = payedDate;
				offer.PaymentType = paymentType;
				offer.ProcessedBy = processedBy;
				offer.Tax = tax;
				offer.Sum = sum;
				offer.Comment = comment;
				offer.AdminComment = adminComment;
				offer.StoreID = storeId;
				offer.IsPayed = isPayed;
				offer.IsSealed = isSealed;
				Entities.SaveChanges();
				return true;
			}
			return false;
		}

		public void DeleteOffer(int storeOfferId) {
			//TODO: No delete just mark as deleted
			StoreOffer offer = Entities.StoreOffers.Where(o => o.OfferID == storeOfferId).SingleOrDefault();
			if (offer != null) {
				Entities.StoreOffers.DeleteObject(offer);
				Entities.SaveChanges();
			}
		}

		public StoreOffer GetOffer(int storeOfferId) {
			StoreOffer storeOffer = Entities.StoreOffers.Where(o => o.OfferID == storeOfferId).SingleOrDefault();
			if (storeOffer == null) throw  new Exception("No such order");
			return storeOffer;
		}

		public bool SealOffer(int storeOfferId)
		{
			StoreOffer storeOffer = GetOffer(storeOfferId);
			if (storeOffer.IsSealed) return false;

			foreach (var item in GetOfferItems(storeOfferId))
			{
				storeOffer.Sum += item.PriceSum;
			}
			
			storeOffer.IsSealed = true;
			Entities.SaveChanges();
			return true;
		}


		public bool IsOfferSealed(int storeOfferId)
		{
			StoreOffer storeOffer = GetOffer(storeOfferId);
			return storeOffer.IsSealed;
		}


		public bool IsOfferPayed(int storeOfferId)
		{
			StoreOffer storeOffer = GetOffer(storeOfferId);
			return storeOffer.IsPayed != null && (bool) storeOffer.IsPayed;
		}

#endregion

#region StoreOfferItems
		//TODO: make two methods, when you know catalogItemId and when you dont
		public StoreOfferItem AddItemToOffer(int storeOfferId, int catalogItemId, decimal quantity, double? discount = null ) {
			if (IsOfferSealed(storeOfferId)) return null;

			StoreCatalogItem storeCatalogItem = storeCatalogItemProvider.Get(catalogItemId);

			decimal priceSum = quantity * storeCatalogItem.PricePerItem;
			if (discount != null) priceSum *= (decimal)discount;

			StoreOfferItem item = new StoreOfferItem {
				StoreCatalogItemID = catalogItemId,
				Discount = discount.IfNullSet(0),
				Quantity = quantity,
				OfferID = storeOfferId,
				PricePerItem = storeCatalogItem.PricePerItem,
				PriceSum = priceSum
			};
			Entities.StoreOfferItems.AddObject(item);
			Entities.SaveChanges();
			return item;
		}


		public bool EditOfferItem(int storeOfferItemId, int storeCatalogItemId, double? discount, decimal? quantity, int offerId) {
			StoreOfferItem item =
				 Entities.StoreOfferItems.Where(i => i.StoreOfferItemID == storeOfferItemId).SingleOrDefault();
			if (item != null) {
				item.StoreCatalogItemID = storeCatalogItemId;
				item.Discount = discount;
				item.Quantity = quantity;
				item.OfferID = offerId;
				Entities.SaveChanges();
				return true;
			}

			return false;
		}

		public void DeleteOfferItem(int storeOfferItemId) {
			StoreOfferItem item =
				 Entities.StoreOfferItems.Where(i => i.StoreOfferItemID == storeOfferItemId).SingleOrDefault();
			if (item != null) {
				Entities.StoreOfferItems.DeleteObject(item);
				Entities.SaveChanges();
			}
		}

		public StoreOfferItem GetOfferItem(int storeCatalogItemId) {
			StoreOfferItem item =
				 Entities.StoreOfferItems.Where(i => i.StoreOfferItemID == storeCatalogItemId).SingleOrDefault();
			if (item != null) {
				return item;
			} else {
				return null;
			}
		}

		public List<StoreOfferItem> GetOfferItems(int offerId) {
			return Entities.StoreOfferItems.Where(i => i.OfferID == offerId).ToList();
		}
		#endregion

	}
}
